# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# The ncurses C library and unit test.

load("//bazel:automake_substitution.bzl", "automake_substitution")
load("//bazel:pseudo_configure.bzl", "pseudo_configure")

package(default_visibility = ["//visibility:public"])

licenses(["notice"])

exports_files([
    "LICENSE",
    "include/Caps",
])

NCURSES_COPTS = [
    "-w",
    "-DTRACE",
    "-DHAVE_CONFIG_H",
    "-D_GNU_SOURCE",
    "-DNDEBUG",
]

CAPLIST = [
    "include/Caps",
    "include/Caps-ncurses",
]

CAPLIST_LOCATIONS = " ".join(["$(location :" + cap + ")" for cap in CAPLIST])

AUTOMAKE_SUBSTITUTIONS = {
    "NCURSES_MAJOR": "6",
    "NCURSES_MINOR": "4",
    "NCURSES_PATCH": "20221231",
    "NCURSES_MOUSE_VERSION": "2",
    "NCURSES_CONST": "const",
    "NCURSES_INLINE": "inline",
    "NCURSES_SBOOL": "char",
    "NCURSES_USE_DATABASE": "1",
    "NCURSES_USE_TERMCAP": "0",
    "NCURSES_XNAMES": "1",
    "HAVE_TERMIOS_H": "1",
    "HAVE_TCGETATTR": "1",
    "HAVE_TERMIO_H": "1",
    "NCURSES_EXT_COLORS": "0",
    "BROKEN_LINKER": "0",
    "cf_cv_enable_reentrant": "0",
    "NCURSES_TPARM_VARARGS": "1",
    "NCURSES_TPARM_ARG": "intptr_t",
    "HAVE_STDINT_H": "1",
    "HAVE_STDNORETURN_H": "1",
    "cf_cv_header_stdbool_h": "1",
    "NCURSES_OPAQUE": "0",
    "NCURSES_OPAQUE_FORM": "0",
    "NCURSES_OPAQUE_MENU": "0",
    "NCURSES_OPAQUE_PANEL": "0",
    "NCURSES_WATTR_MACROS": "1",
    "NCURSES_INTEROP_FUNCS": "1",
    "NCURSES_SIZE_T": "short",
    "NCURSES_CH_T": "cchar_t",
    "cf_cv_enable_lp64": "1",
    "cf_cv_type_of_bool": "unsigned char",
    "USE_CXX_BOOL": "defined(__cplusplus)",
    "NCURSES_EXT_FUNCS": "1",
    "NCURSES_LIBUTF8": "0",
    "NEED_WCHAR_H": "1",
    "NCURSES_WCHAR_T": "0",
    "NCURSES_OK_WCHAR_T": "",
    "NCURSES_CCHARW_MAX": "5",
    "NCURSES_WCWIDTH_GRAPHICS": "1",
    "GENERATED_EXT_FUNCS": "generated",
    "NCURSES_SP_FUNCS": "1",
    "cf_cv_1UL": "1U",
    "HAVE_VSSCANF": "1",
    "NCURSES_WINT_T": "0",
    "NCURSES_OSPEED": "short",
    "cf_cv_typeof_chtype": "cchar_t",
    "cf_cv_typeof_mmask_t": "unsigned",
    "NCURSES_WRAP_PREFIX": "_nc_",
    "EXP_WIN32_DRIVER": "0",
    "USE_WIDEC_SUPPORT": "1",
    "NCURSES_WIDECHAR": "1",
    "HAVE_WCHAR_H": "1",
    "HAVE_WCTYPE_H": "1",
    "HAVE_PUTWC": "1",
    "HAVE_BTOWC": "1",
    "HAVE_WCTOB": "1",
    "HAVE_WMEMCHR": "1",
    "HAVE_MBTOWC": "1",
    "HAVE_WCTOMB": "1",
    "HAVE_MBLEN": "1",
    "HAVE_MBRLEN": "1",
    "HAVE_MBRTOWC": "1",
    "HAVE_WCSRTOMBS": "1",
    "HAVE_MBSRTOWCS": "1",
    "HAVE_WCSTOMBS": "1",
    "HAVE_MBSTOWCS": "1",
    "NCURSES_MBSTATE_T": "1",
}

cc_library(
    name = "ncurses_headers",
    hdrs = glob(["include/*"]) + [
        # Generated files are not found by glob.
        "include/hashsize.h",
        "include/ncurses_cfg.h",
        "include/ncurses_def.h",
        "include/parametrized.h",
        "include/curses.h",
        "include/term.h",
        "include/ncurses_dll.h",
        "include/unctrl.h",
        "include/termcap.h",
        # Various source files include these, so call them headers.
        "ncurses/tinfo/doalloc.c",
        "ncurses/names.c",
    ],
    includes = [
        "include",
        "ncurses",
    ],
)

cc_library(
    name = "ncurses",
    srcs = glob(
        [
            "ncurses/base/*.c",
            "ncurses/*.c",
            "ncurses/*.h",
            "ncurses/tinfo/*.c",
            "ncurses/trace/*.c",
            "ncurses/tty/*.c",
            "ncurses/widechar/*.c",
        ],
        exclude = glob([
            "ncurses/base/lib_driver.c",
            "ncurses/base/sigaction.c",
            "ncurses/tinfo/make_keys.c",
            "ncurses/tinfo/tinfo_driver.c",
            "ncurses/tinfo/make_hash.c",
            "ncurses/report_offsets.c",
            "ncurses/report_hashing.c",
        ]),
    ) + [
        # Generated files are not found by glob.
        "ncurses/codes.c",
        "ncurses/comp_captab.c",
        "ncurses/comp_userdefs.c",
        "ncurses/fallback.c",
        "ncurses/init_keytry.h",
        "ncurses/lib_gen.c",
        "ncurses/lib_keyname.c",
        "ncurses/names.c",
        "ncurses/unctrl.c",
    ],
    copts = NCURSES_COPTS,
    deps = [":ncurses_headers"],
)

# Common headers between form and menu.
cc_library(
    name = "mf_common",
    hdrs = [
        "menu/eti.h",
        "menu/mf_common.h",
    ],
    includes = ["menu"],
)

cc_library(
    name = "form",
    srcs = glob(["form/*.c"]) + [
        "form/form.priv.h",
        "ncurses/curses.priv.h",
    ],
    hdrs = ["form/form.h"],
    copts = NCURSES_COPTS,
    deps = [
        ":mf_common",
        ":ncurses",
    ],
)

cc_library(
    name = "menu",
    srcs = glob(["menu/*.c"]) + [
        "menu/menu.priv.h",
        "ncurses/curses.priv.h",
    ],
    hdrs = ["menu/menu.h"],
    copts = NCURSES_COPTS,
    deps = [
        ":mf_common",
        ":ncurses",
    ],
)

cc_library(
    name = "panel",
    srcs = glob(["panel/*.c"]) + [
        "ncurses/curses.priv.h",
        "panel/panel.priv.h",
    ],
    hdrs = [
        "panel/panel.h",
    ],
    copts = NCURSES_COPTS,
    deps = [":ncurses"],
)

genrule(
    name = "fallback_c",
    srcs = ["misc/terminfo.src"],
    outs = ["ncurses/fallback.c"],
    cmd = "$(location :ncurses/tinfo/MKfallback.sh) /usr/share/terminfo $(location :misc/terminfo.src) $$(which tic) $$(which infocmp) > $@",
    tools = ["ncurses/tinfo/MKfallback.sh"],
)

cc_binary(
    name = "make_hash",
    srcs = [
        "ncurses/build.priv.h",
        "ncurses/curses.priv.h",
        "ncurses/tinfo/make_hash.c",
    ],
    copts = NCURSES_COPTS,
    deps = [":ncurses_headers"],
)

genrule(
    name = "comp_captab_c",
    srcs = [
        "ncurses/tinfo/MKcaptab.awk",
        "include/Caps",
    ],
    outs = ["ncurses/comp_captab.c"],
    cmd = "cp -f $(location :make_hash) . && $(location :ncurses/tinfo/MKcaptab.sh) $$(which awk) 1 $(location :ncurses/tinfo/MKcaptab.awk) $(location :include/Caps) > $@",
    tools = [
        "ncurses/tinfo/MKcaptab.sh",
        ":make_hash",
    ],
)

genrule(
    name = "comp_userdefs_c",
    srcs = ["include/hashsize.h"] + CAPLIST,
    outs = ["ncurses/comp_userdefs.c"],
    cmd = "cp -f $(location :make_hash) . && $(location ncurses/tinfo/MKuserdefs.sh) $$(which awk) 1 " + CAPLIST_LOCATIONS + " > $@",
    tools = [
        "ncurses/tinfo/MKuserdefs.sh",
        ":make_hash",
    ],
)

genrule(
    name = "codes_c",
    srcs = [
        "ncurses/tinfo/MKcodes.awk",
        "include/Caps",
    ],
    outs = ["ncurses/codes.c"],
    cmd = "/usr/bin/env awk -f $(location ncurses/tinfo/MKcodes.awk) bigstrings=1 $(location :include/Caps) > $@",
)

genrule(
    name = "names_c",
    srcs = [
        "ncurses/tinfo/MKnames.awk",
        "include/Caps",
    ],
    outs = ["ncurses/names.c"],
    cmd = "/usr/bin/env awk -f $(location :ncurses/tinfo/MKnames.awk) bigstrings=1 $(location :include/Caps) > $@",
)

genrule(
    name = "unctrl_c",
    srcs = [
        "ncurses/base/MKunctrl.awk",
    ],
    outs = ["ncurses/unctrl.c"],
    cmd = "/usr/bin/env awk -f $(location :ncurses/base/MKunctrl.awk) bigstrings=1 > $@",
)

cc_binary(
    name = "make_keys",
    srcs = [
        "ncurses/build.priv.h",
        "ncurses/curses.priv.h",
        "ncurses/tinfo/make_keys.c",
    ],
    copts = NCURSES_COPTS,
    deps = [":ncurses_headers"],
)

genrule(
    name = "keys_list",
    srcs = ["include/Caps"],
    outs = ["keys.list"],
    cmd = "$(location :ncurses/tinfo/MKkeys_list.sh) $(location :include/Caps) | LC_ALL=C sort > $@",
    tools = ["ncurses/tinfo/MKkeys_list.sh"],
)

genrule(
    name = "lib_keyname_c",
    srcs = [
        "ncurses/base/MKkeyname.awk",
        "keys.list",
    ],
    outs = ["ncurses/lib_keyname.c"],
    cmd = "/usr/bin/env awk -f $(location :ncurses/base/MKkeyname.awk) bigstrings=1 $(location :keys.list) > $@",
)

automake_substitution(
    name = "curses_head",
    src = "include/curses.h.in",
    out = "include/curses.head",
    substitutions = AUTOMAKE_SUBSTITUTIONS,
)

automake_substitution(
    name = "curses_dll",
    src = "include/ncurses_dll.h.in",
    out = "include/ncurses_dll.h",
    substitutions = AUTOMAKE_SUBSTITUTIONS,
)

automake_substitution(
    name = "unctrl_h",
    src = "include/unctrl.h.in",
    out = "include/unctrl.h",
    substitutions = AUTOMAKE_SUBSTITUTIONS,
)

automake_substitution(
    name = "termcap_h",
    src = "include/termcap.h.in",
    out = "include/termcap.h",
    substitutions = AUTOMAKE_SUBSTITUTIONS,
)

genrule(
    name = "curses_h",
    srcs = [
        "include/curses.head",
        "include/curses.tail",
        "include/curses.wide",
    ] + CAPLIST,
    outs = ["include/curses.h"],
    cmd = "cat $(location :include/curses.head) > $@ && AWK=$$(which awk) $(location :include/MKkey_defs.sh) " + CAPLIST_LOCATIONS + " >> $@ && cat $(location :include/curses.wide) $(location :include/curses.tail) >> $@",
    tools = ["include/MKkey_defs.sh"],
)

genrule(
    name = "lib_gen_c",
    srcs = [
        "include/curses.h",
        "include/ncurses_cfg.h",
        "include/ncurses_def.h",
    ],
    outs = ["ncurses/lib_gen.c"],
    cmd = "$(location :ncurses/base/MKlib_gen.sh) \"$(CC) -E -isystem $$(dirname $(location :include/ncurses_cfg.h))\" $$(which awk) generated < $(location :include/curses.h) > $@",
    tools = ["ncurses/base/MKlib_gen.sh"],
    toolchains = ["@rules_cc//cc:current_cc_toolchain"],
)

genrule(
    name = "hashsize_h",
    srcs = ["include/Caps"],
    outs = ["include/hashsize.h"],
    cmd = "$(location :include/MKhashsize.sh) $(location :include/Caps) > $@",
    tools = ["include/MKhashsize.sh"],
)

genrule(
    name = "init_keytry_h",
    srcs = ["keys.list"],
    outs = ["ncurses/init_keytry.h"],
    cmd = "$(location :make_keys) $(location :keys.list) > $@",
    tools = [":make_keys"],
)

automake_substitution(
    name = "mkterm_h_awk",
    src = "include/MKterm.h.awk.in",
    out = "include/MKterm.h.awk",
    substitutions = AUTOMAKE_SUBSTITUTIONS,
)

genrule(
    name = "term_h",
    srcs = [
        "include/MKterm.h.awk",
        "include/Caps",
    ],
    outs = ["include/term.h"],
    cmd = "/usr/bin/env awk -f $(location :include/MKterm.h.awk) $(location :include/Caps) > $@",
)

genrule(
    name = "parametrized_h",
    srcs = ["include/Caps"],
    outs = ["include/parametrized.h"],
    cmd = "(cd $$(dirname $(location :include/MKparametrized.sh)) && ./MKparametrized.sh) > $@",
    tools = ["include/MKparametrized.sh"],
)

genrule(
    name = "ncurses_def_h",
    srcs = ["include/ncurses_defs"],
    outs = ["include/ncurses_def.h"],
    cmd = "(cd $$(dirname $(location :include/MKncurses_def.sh)) && ./MKncurses_def.sh) > $@",
    tools = ["include/MKncurses_def.sh"],
)

pseudo_configure(
    name = "ncurses_cfg_h",
    src = "include/ncurses_cfg.hin",
    out = "include/ncurses_cfg.h",
    defs = [
        "HAVE_LONG_FILE_NAMES",
        "MIXEDCASE_FILENAMES",
        "HAVE_BIG_CORE",
        "PURE_TERMINFO",
        "USE_HOME_TERMINFO",
        "USE_ROOT_ENVIRON",
        "HAVE_UNISTD_H",
        "HAVE_REMOVE",
        "HAVE_UNLINK",
        "HAVE_LINK",
        "HAVE_SYMLINK",
        "USE_LINKS",
        "HAVE_LANGINFO_CODESET",
        "HAVE_FSEEKO",
        "STDC_HEADERS",
        "HAVE_SYS_TYPES_H",
        "HAVE_SYS_STAT_H",
        "HAVE_STDLIB_H",
        "HAVE_STRING_H",
        "HAVE_MEMORY_H",
        "HAVE_STRINGS_H",
        "HAVE_INTTYPES_H",
        "HAVE_STDINT_H",
        "HAVE_UNISTD_H",
        "SIZEOF_SIGNED_CHAR",
        "NCURSES_EXT_FUNCS",
        "HAVE_ASSUME_DEFAULT_COLORS",
        "HAVE_CURSES_VERSION",
        "HAVE_HAS_KEY",
        "HAVE_RESIZETERM",
        "HAVE_RESIZE_TERM",
        "HAVE_TERM_ENTRY_H",
        "HAVE_USE_DEFAULT_COLORS",
        "HAVE_USE_EXTENDED_NAMES",
        "HAVE_USE_SCREEN",
        "HAVE_USE_WINDOW",
        "HAVE_WRESIZE",
        "NCURSES_SP_FUNCS",
        "HAVE_TPUTS_SP",
        "NCURSES_EXT_PUTWIN",
        "NCURSES_NO_PADDING",
        "USE_SIGWINCH",
        "USE_ASSUMED_COLOR",
        "USE_HASHMAP",
        "GCC_SCANF",
        "GCC_PRINTF",
        "HAVE_NC_ALLOC_H",
        "HAVE_GETTIMEOFDAY",
        "STDC_HEADERS",
        "HAVE_DIRENT_H",
        "TIME_WITH_SYS_TIME",
        "HAVE_REGEX_H_FUNCS",
        "HAVE_FCNTL_H",
        "HAVE_GETOPT_H",
        "HAVE_LIMITS_H",
        "HAVE_LOCALE_H",
        "HAVE_MATH_H",
        "HAVE_POLL_H",
        "HAVE_SYS_IOCTL_H",
        "HAVE_SYS_PARAM_H",
        "HAVE_SYS_POLL_H",
        "HAVE_SYS_SELECT_H",
        "HAVE_SYS_TIME_H",
        "HAVE_SYS_TIMES_H",
        "HAVE_TTYENT_H",
        "HAVE_UNISTD_H",
        "HAVE_WCTYPE_H",
        "HAVE_UNISTD_H",
        "HAVE_GETOPT_H",
        "HAVE_GETOPT_HEADER",
        "DECL_ENVIRON",
        "HAVE_ENVIRON",
        "HAVE_PUTENV",
        "HAVE_SETENV",
        "HAVE_STRDUP",
        "HAVE_SYS_TIME_SELECT",
        "HAVE_GETCWD",
        "HAVE_GETEGID",
        "HAVE_GETEUID",
        "HAVE_GETOPT",
        "HAVE_GETTTYNAM",
        "HAVE_LOCALECONV",
        "HAVE_POLL",
        "HAVE_PUTENV",
        "HAVE_REMOVE",
        "HAVE_SELECT",
        "HAVE_SETBUF",
        "HAVE_SETBUFFER",
        "HAVE_SETENV",
        "HAVE_SETVBUF",
        "HAVE_SIGACTION",
        "HAVE_STRDUP",
        "HAVE_STRSTR",
        "HAVE_SYSCONF",
        "HAVE_TCGETPGRP",
        "HAVE_TIMES",
        "HAVE_TSEARCH",
        "HAVE_VSNPRINTF",
        "HAVE_ISASCII",
        "HAVE_NANOSLEEP",
        "HAVE_TERMIO_H",
        "HAVE_TERMIOS_H",
        "HAVE_UNISTD_H",
        "HAVE_SYS_IOCTL_H",
        "HAVE_TCGETATTR",
        "HAVE_VSSCANF",
        "HAVE_UNISTD_H",
        "HAVE_MKSTEMP",
        "HAVE_SIZECHANGE",
        "HAVE_WORKING_POLL",
        "HAVE_VA_COPY",
        "HAVE_UNISTD_H",
        "HAVE_FORK",
        "HAVE_VFORK",
        "HAVE_WORKING_VFORK",
        "HAVE_WORKING_FORK",
        "USE_FOPEN_BIN_R",
        "USE_XTERM_PTY",
        "HAVE_TYPEINFO",
        "HAVE_IOSTREAM",
        "IOSTREAM_NAMESPACE",
        "CPP_HAS_STATIC_CAST",
        "HAVE_SLK_COLOR",
        "HAVE_PANEL_H",
        "HAVE_LIBPANEL",
        "HAVE_MENU_H",
        "HAVE_LIBMENU",
        "HAVE_FORM_H",
        "HAVE_LIBFORM",
        "NCURSES_OSPEED_COMPAT",
        "HAVE_CURSES_DATA_BOOLNAMES",
        "NCURSES_WIDECHAR",
        "USE_WIDEC_SUPPORT",
        "HAVE_WCHAR_H",
        "HAVE_WCTYPE_H",
        "HAVE_PUTWC",
        "HAVE_BTOWC",
        "HAVE_WCTOB",
        "HAVE_WMEMCHR",
        "HAVE_MBTOWC",
        "HAVE_WCTOMB",
        "HAVE_MBLEN",
        "HAVE_MBRLEN",
        "HAVE_MBRTOWC",
        "HAVE_WCSRTOMBS",
        "HAVE_MBSRTOWCS",
        "HAVE_WCSTOMBS",
        "HAVE_MBSTOWCS",
        "NEED_WCHAR_H",
    ],
    mappings = {
        "NC_CONFIG_H": "",
        "PACKAGE": '"ncurses"',
        "NCURSES_VERSION": '"6.4"',
        "NCURSES_PATCHDATE": "20200212",
        "SYSTEM_NAME": '"linux-gnu"',
        "TERMINFO_DIRS": r'"\/usr\/share\/terminfo"',
        "TERMINFO": r'"\/usr\/share\/terminfo"',
        "RGB_PATH": r'"\/usr\/share\/X11\/rgb.txt"',
        "NCURSES_WRAP_PREFIX": '"_nc_"',
        "GCC_SCANFLIKE(fmt,var)": "__attribute__((format(scanf,fmt,var)))",
        "GCC_PRINTFLIKE(fmt,var)": "__attribute__((format(printf,fmt,var)))",
        "GCC_UNUSED": "__attribute__((unused))",
        "GCC_NORETURN": "__attribute__((noreturn))",
        "SIG_ATOMIC_T": "volatile sig_atomic_t",
        "USE_OPENPTY_HEADER": "<pty.h>",
        "NCURSES_PATHSEP": "0x3a",
        "NCURSES_VERSION_STRING": '"6.4.20221231"',
    },
)
